|
ARD2
RC2
Airbag Reference Demonstrator using MPC5604P
|
00001 00020 #include "Compile_Options.h" 00021 #include "derivative.h" 00022 #include "ADC.h" 00023 #include "CG147.h" 00024 #include "eDMA.h" /* To Have periodic watchdog transfers */ 00025 #include "PIT.h" /* Same as above */ 00026 #include "DSPI.h" /* To send and receive */ 00027 #include "CGM.h" /* To configure 2MHz clock output through CLKOUT */ 00028 #include "MailScheduler.h" 00029 #include "HAL.h" /* To use delay macros */ 00030 #include "SIU.h" /* To toggle pins */ 00031 #include "UTILS.h" 00032 #include <limits.h> 00033 /* 00034 ****************************************************************************** 00035 * Constants 00036 ****************************************************************************** 00037 */ 00038 const CGMCLKOutConfig_t ctCG147ClkOutConfig = 00039 { 00040 (CLK_OUT_ENABLE | CLK_OUT_DIV_BY_8 | CLK_OUT_SOURCE_PLL1) }; 00041 /* Next two constants are used to read all PSI5 sensors in order */ 00042 /* First command selects channel 0 for the next command. */ 00043 /* The next commands are always acceleration requests, and arguments select */ 00044 /* the channel for then upcoming request. */ 00045 const uint8_t cau8ReadPSISensorsCmd[] = 00046 { 00047 SBC_SELECT_PSI, SBC_READ_PSI, SBC_READ_PSI, SBC_READ_PSI, SBC_READ_PSI, 00048 SBC_READ_PSI, SBC_READ_PSI, SBC_READ_PSI, SBC_READ_PSI, SBC_READ_PSI, 00049 SBC_READ_PSI, SBC_READ_PSI, SBC_READ_PSI }; 00050 const uint8_t cau8ReadPSISensorsArg[] = 00051 { 00052 0x00, 0x01, 0x02, 0x04, 0x05, 0x06, 0x08, 0x09, 0x0A, 0x0C, 0x0D, 0x0E, 00053 0x00 }; 00054 /* Next two commands shall be used in 16-bit mode to configure the device */ 00055 /* and switch to 17-bit mode. */ 00056 const uint8_t cau8CG147InitCmdsIn16Bit[] = 00057 { 00058 SBC_POWER_CTRL, /* Remove EMC noise coming from DC-DC converter */ 00059 SBC_ENABLE_PROG, /* Allow the following operations to take place */ 00060 SBC_PROG_POWER, /* Program power */ 00061 SBC_PROG_PSI1_LINE, /* Slew rate control off, 10-bt, single slot, parity, 125k, synchronous */ 00062 SBC_PROG_PSI2_LINE, /* Slew rate control off, 10-bt, single slot, parity, 125k, synchronous */ 00063 SBC_PROG_PSI3_LINE, /* Slew rate control off, 10-bt, single slot, parity, 125k, synchronous */ 00064 SBC_PROG_PSI4_LINE, /* Slew rate control off, 10-bt, single slot, parity, 125k, synchronous */ 00065 SBC_PROG_PSYNC_MODE, /* Detect reg off, i reg on, time slot on, manual psync, 2usec between ch */ 00066 SBC_PSI_SUPPLY, /* All four power supplies on */ 00067 SBC_PSI_SYNC_MASK, /* All four PSI5 channels on */ 00068 SBC_PROG_PSI_SID, /* SBC_PROG_PSI_SID => otherwise default SID=111 */ 00069 SBC_PROG_PSI_SID, /* SBC_PROG_PSI_SID => otherwise default SID=111 */ 00070 SBC_PROG_PSI_SID, /* SBC_PROG_PSI_SID => otherwise default SID=111 */ 00071 SBC_PROG_PSI_SID, /* SBC_PROG_PSI_SID => otherwise default SID=111 */ 00072 SBC_PROG_UFS_THRES, /* Thresholds */ 00073 SBC_PROG_PAS_THRES, /* Thresholds */ 00074 SBC_PROG_PRES_THRES, /* Thresholds */ 00075 SBC_PROG_ROLL_THRES, /* Thresholds */ 00076 SBC_PROG_X_THRES, /* Thresholds */ 00077 SBC_PROG_Y_THRES, /* Thresholds */ 00078 SBC_PROG_FLM_CONF, /* This configures firing time and current */ 00079 SBC_PROG_ENH_SAFETY /* SPI Data will necessarily be 17-bit transfers after this */ 00080 /* Note that EOP is missing - it must be sent as a 17-bit word now */ 00081 }; 00082 const uint8_t cau8CG147InitArgsIn16Bit[] = 00083 { 00084 CG147_DEFAULT_POWER_STG, /* Remove EMC noise coming from DC-DC converter */ 00085 0x02u, /* Allow the following operations to take place */ 00086 0x00u, /* Program power */ 00087 0x40u, /* Slew rate control off, 10-bt, single slot, parity, 125k, synchronous */ 00088 0x40u, /* Slew rate control off, 10-bt, single slot, parity, 125k, synchronous */ 00089 0x40u, /* Slew rate control off, 10-bt, single slot, parity, 125k, synchronous */ 00090 0x40u, /* Slew rate control off, 10-bt, single slot, parity, 125k, synchronous */ 00091 0xC1u, /* Detect reg off, i reg on, time slot on, manual psync, 2usec between ch */ 00092 0xCFu, /* All four power supplies on */ 00093 0x0Fu, /* All four PSI5 channels on */ 00094 0x00u, /* SBC_PROG_PSI_SID => otherwise default SID=111 */ 00095 0x20u, /* SBC_PROG_PSI_SID => otherwise default SID=111 */ 00096 0x40u, /* SBC_PROG_PSI_SID => otherwise default SID=111 */ 00097 0x60u, /* SBC_PROG_PSI_SID => otherwise default SID=111 */ 00098 0x05u, /* Thresholds */ 00099 0x05u, /* Thresholds */ 00100 0x00u, /* Thresholds */ 00101 0x00u, /* Thresholds */ 00102 0x00u, /* Thresholds */ 00103 0x00u, /* Thresholds */ 00104 0x00u, /* This configures firing time and current */ 00105 0x0Cu /* SPI Data will necessarily be 17-bit transfers after this */ 00106 /* Note that EOP is missing - it must be sent as a 17-bit word now */ 00107 }; 00108 /* Next value is used to determine size of previous two elements */ 00109 const uint8_t cu8CG147InitCmdsArgsSize = N_ELEMENTS(cau8CG147InitCmdsIn16Bit); 00110 /* Following three tables are used when addressing both high side and low */ 00111 /* side squibs, and by default turning them off. */ 00112 static const uint8_t cau8CG147FireLSSquibsCmds[] = 00113 { 00114 SBC_LS_ON1_4, SBC_LS_ON5_8, SBC_LS_ON9_12 }; 00115 static const uint8_t cau8CG147FireHSSquibsCmds[] = 00116 { 00117 SBC_HS_ON1_4, SBC_HS_ON5_8, SBC_HS_ON9_12, }; 00118 static const uint8_t cau8CG147FireSquibsDfltArgs[] = 00119 { 00120 0xAA, /* HS_ON1_4: By default, all off. User should edit before sending */ 00121 0xAA, /* HS_ON5_8: By default, all off. User should edit before sending */ 00122 0xAA, /* HS_ON9_12 By default, all off. User should edit before sending */ 00123 }; 00124 /* Following tables are used when performing tests */ 00125 static const uint8_t cau8CG147TestCmds[] = 00126 { 00127 SBC_POWER_CTRL, /* First instruction is to disable T2 */ 00128 SBC_POWER_CTRL, /* Second instruction will be overwritten with a test */ 00129 SBC_POWER_STATUS, /* Third will get the condition back */ 00130 SBC_POWER_CTRL, /* Fourth will re-establish original settings */ 00131 }; 00132 static const uint8_t cau8CG147TestArgs[] = 00133 { 00134 /* With the T_EN bit within the SPI instruction POWER_CTRL being set */ 00135 /* the transistor T2 of the boost converter is switched off. */ 00136 0x01u, 00137 /* Second argument is the test itself and should be overwritten by */ 00138 /* the actual command. Here set to FF as a place-holder. */ 00139 0xFFu, 00140 /* Verify the actual result */ 00141 0x00u, 00142 /* Re-establish default settings */ 00143 CG147_DEFAULT_POWER_STG }; 00144 00145 /* Next two constants serve as a list of Watch-dog responses. */ 00146 const uint8_t cau8CG147WDResponsesFromMCU[] = 00147 { 00148 SBC_WD_RESPONSE_8, SBC_WD_RESPONSE_1, SBC_WD_RESPONSE_2, SBC_WD_RESPONSE_3, 00149 SBC_WD_RESPONSE_4, SBC_WD_RESPONSE_5, SBC_WD_RESPONSE_6, SBC_WD_RESPONSE_7 }; 00150 const uint8_t cau8CG147WDRequestsToMCU[] = 00151 { 00152 SBC_WD_CHECKWORD_1, SBC_WD_CHECKWORD_2, SBC_WD_CHECKWORD_3, 00153 SBC_WD_CHECKWORD_4, SBC_WD_CHECKWORD_5, SBC_WD_CHECKWORD_6, 00154 SBC_WD_CHECKWORD_7, SBC_WD_CHECKWORD_8 }; 00155 00156 /* Following table is a pre-calculation of all possible combinations */ 00157 /* for a squib register being either on or off. It is used in combi- */ 00158 /* nation with a mask to be sent as an argument to the CG147 device. */ 00159 const uint8_t cau8SquibOnPrecalc[] = 00160 { 00161 0xAA, 0xA9, 0xA6, 0xA5, 0x9A, 0x99, 0x96, 0x95, 0x6A, 0x69, 0x66, 0x65, 0x5A, 00162 0x59, 0x56, 0x55 }; 00163 /* 00164 ****************************************************************************** 00165 * Globals 00166 ****************************************************************************** 00167 */ 00168 /* Variable below is used for non-scheduled responses. To be deprecated */ 00169 uint16_t gau16CG147Responses[CG147_INPUT_BUFFER_SIZE]; 00170 uint32_t gau32CG147DefaultResponses[CG147_INPUT_BUFFER_SIZE]; 00172 uint8_t gu8CG147WatchDog2ResponseFromMCU; 00174 uint8_t gu8CG147WatchDog3ResponseFromMCU; 00176 uint32_t gu32CG147WatchDog2RequestToMCU; 00178 uint32_t gu32CG147WatchDog3RequestToMCU; 00180 uint16_t gu16CG147WatchDog2IsrCount; 00182 uint16_t gu16CG147WatchDog3IsrCount; 00183 /* Variables below are used to remember configuration from the user */ 00185 uint8_t gu8CG147DSPIInstance; 00187 uint8_t gu8CG147DSPICS; 00189 uint8_t gau8CG147DSPIComplexInstances[2u]; 00191 uint32_t gu32CG147WD2Time; 00193 uint32_t gu32CG147WD3Time; 00195 uint32_t gu32CG147WDStatus; 00196 /* 00197 ****************************************************************************** 00198 * Function : vfnCG147Init() 00199 ****************************************************************************** 00200 */ 00201 void vfnCG147Init(const uint8_t cu8DSPIMainInstance, 00202 const uint8_t cu8ChipSelect, 00203 const uint8_t cu8DSPISecondaryInstance1, 00204 const uint8_t cu8DSPISecondaryInstance2, 00205 const uint8_t cu8NSysResPort, 00206 const uint8_t cu8NSysResPin) 00207 { 00208 /* We're going to reset the internal logic of the CG147 now - delays are */ 00209 /* necessary to ensure correct reset behavior of the device. We justify */ 00210 /* them because this function should only be called once during start-up. */ 00211 vfnToggleOutputPin(cu8NSysResPort, cu8NSysResPin, TRUE); 00212 DELAY_MSEC(250u); 00213 vfnToggleOutputPin(cu8NSysResPort, cu8NSysResPin, CLEAR); 00214 DELAY_MSEC(38u); 00215 vfnToggleOutputPin(cu8NSysResPort, cu8NSysResPin, TRUE); 00216 DELAY_MSEC(250u); 00217 00218 /* Start 2MHz clock through CLKOUT */ 00219 vfnClockOutputEnable(ctCG147ClkOutConfig); 00220 00221 /* Next, we init our watchdog 3 with the passed timer channel and counts */ 00222 (void)u8fnCG147WatchDogStartUp(); 00223 00224 /* Remember what DSPI instance and chip select are being used */ 00225 gu8CG147DSPICS = cu8ChipSelect; 00226 gu8CG147DSPIInstance = cu8DSPIMainInstance; 00227 gau8CG147DSPIComplexInstances[CLEAR] = cu8DSPISecondaryInstance1; 00228 gau8CG147DSPIComplexInstances[1u] = cu8DSPISecondaryInstance2; 00229 00230 return; 00231 } 00232 /* 00233 ****************************************************************************** 00234 * Function : u8fnCG147ReadAOut() 00235 * Functional with Direct SPI Tx in 16-bit configuration ONLY 00236 ****************************************************************************** 00237 */ 00238 uint8_t u8fnCG147ReadAOut(const uint8_t cu8DSPIInstance, 00239 const uint8_t cu8ChipSelect, 00240 const uint8_t cu8ADCInstance, 00241 const uint8_t cu8ADCCh, 00242 const uint8_t cu8CG147Ch, 00243 uint16_t* pu16Result) 00244 { 00245 00246 /* Declare local variables */ 00247 uint8_t u8Status; 00248 00249 /* Init local variables */ 00250 u8Status = CLEAR; 00251 00252 /* Ask the CG147 to output ADC data */ 00253 u8Status = u8fnCG147Transcieve(SBC_AOUT_CTRL, 00254 (BIT7 | cu8CG147Ch), 00255 cu8DSPIInstance, 00256 cu8ChipSelect); 00257 00258 if(CLEAR == u8Status) 00259 { 00260 u8Status = u8fnADCConvert(cu8ADCInstance, cu8ADCCh, pu16Result); 00261 } 00262 else 00263 { 00264 /* In this particular case, status is already set to something. Leave it */ 00265 } 00266 00267 return (u8Status); 00268 } 00269 /* 00270 ****************************************************************************** 00271 * Function : u8fnCG147ReadPSI5Accel() 00272 * Functional with Direct SPI Tx in 16-bit configuration ONLY 00273 ****************************************************************************** 00274 */ 00275 uint8_t u8fnCG147ReadPSI5Accel(const uint8_t cu8DSPIInstance, 00276 const uint8_t cu8ChipSelect, 00277 uint16_t* pu16Accel) 00278 { 00279 /* Declare local variables */ 00280 uint8_t u8SPIStatus; 00281 uint8_t u8Counter; 00282 00283 /* Init local variables - keeps MISRA happy */ 00284 u8SPIStatus = CLEAR; 00285 u8Counter = CLEAR; 00286 00287 /* Loop as many times as we have sensors */ 00288 u8SPIStatus = u8fnCG147BatchTranscieve((uint8_t*)cau8ReadPSISensorsCmd, 00289 (uint8_t*)cau8ReadPSISensorsArg, 00290 cu8DSPIInstance, cu8ChipSelect, 00291 N_ELEMENTS(cau8ReadPSISensorsArg)); 00292 /* If we received data correctly, pass that to a global variable */ 00293 if(CLEAR == u8SPIStatus) 00294 { 00295 *pu16Accel++ = u16fn10BitOffsetFilter(gau16CG147Responses[1u]); 00296 *pu16Accel++ = u16fn10BitOffsetFilter(gau16CG147Responses[2u]); 00297 *pu16Accel++ = u16fn10BitOffsetFilter(gau16CG147Responses[3u]); 00298 *pu16Accel++ = u16fn10BitOffsetFilter(gau16CG147Responses[4u]); 00299 } 00300 else 00301 { 00302 for(u8Counter = CLEAR; u8Counter < 4u; u8Counter++) 00303 { 00304 *pu16Accel++ = CLEAR; 00305 } 00306 } /* End else */ 00307 00308 return (u8SPIStatus); 00309 } 00310 /* 00311 ****************************************************************************** 00312 * Function : u8fnCG147ReadPSI5RegSensor() 00313 * Functional with Direct SPI Tx in 16-bit configuration ONLY 00314 ****************************************************************************** 00315 */ 00316 uint8_t u8fnCG147ReadPSI5RegSensor(const uint8_t cu8DSPIInstance, 00317 const uint8_t cu8ChipSelect, 00318 uint16_t* pu16Accel) 00319 { 00320 /* Declare local variables */ 00321 uint8_t u8SPIStatus; 00322 uint8_t u8Counter; 00323 00324 /* Init local variables - keeps MISRA happy */ 00325 u8SPIStatus = CLEAR; 00326 u8Counter = CLEAR; 00327 00328 /* Loop as many times as we have sensors */ 00329 u8SPIStatus = u8fnCG147BatchTranscieve((uint8_t*)cau8ReadPSISensorsCmd, 00330 (uint8_t*)cau8ReadPSISensorsArg, 00331 cu8DSPIInstance, cu8ChipSelect, 00332 N_ELEMENTS(cau8ReadPSISensorsArg)); 00333 /* If we received data correctly, pass that to a global variable */ 00334 if(CLEAR == u8SPIStatus) 00335 { 00336 //Debug register debug at start up 00337 *pu16Accel++ = gau16CG147Responses[1u]; 00338 (void)u8fnDelay(CG147_PULSE_DELAY_20_USEC); 00339 *pu16Accel++ = gau16CG147Responses[2u]; 00340 (void)u8fnDelay(CG147_PULSE_DELAY_20_USEC); 00341 *pu16Accel++ = gau16CG147Responses[3u]; 00342 (void)u8fnDelay(CG147_PULSE_DELAY_20_USEC); 00343 *pu16Accel++ = gau16CG147Responses[4u]; 00344 (void)u8fnDelay(CG147_PULSE_DELAY_20_USEC); 00345 00346 } 00347 else 00348 { 00349 for(; u8Counter < N_ELEMENTS(cau8ReadPSISensorsArg); 00350 u8Counter++) 00351 { 00352 *pu16Accel++ = CLEAR; 00353 } 00354 } /* End else */ 00355 00356 return (u8SPIStatus); 00357 } 00358 /* 00359 ****************************************************************************** 00360 * u8fnCG147Transcieve 00361 * Functional with Direct SPI Tx in 16-bit configuration ONLY 00362 ****************************************************************************** 00363 */ 00364 vuint8_t u8fnCG147Transcieve(uint8_t u8Cmd, 00365 uint8_t u8Value, 00366 uint8_t u8SPIInstance, 00367 uint8_t u8CSToCG147) 00368 { 00369 /* Declare locals */ 00370 uint16_t u16Message; 00371 00372 /* init variables. Note that gau16CG147Responses only inits the first value*/ 00373 gau16CG147Responses[CLEAR] = CLEAR; 00374 00375 /* Construct the message only if NOfMessages can be used by au16Message */ 00376 vfnCG147ComposeFrame(&u8Cmd, &u8Value, (uint16_t*)&u16Message, ((uint8_t)1u)); 00377 00378 return (u8fnDSPITranscieve(u8SPIInstance, 00379 u8CSToCG147, 00380 (uint16_t*)&u16Message, 00381 (uint16_t*)&gau16CG147Responses, 00382 ((uint8_t)1u))); 00383 } 00384 /* 00385 ****************************************************************************** 00386 * u8fnCG147BatchTranscieve 00387 * Functional with Direct SPI Tx in 16-bit configuration ONLY 00388 ****************************************************************************** 00389 */ 00390 uint8_t u8fnCG147BatchTranscieve(uint8_t* pu8Cmd, 00391 uint8_t* pu8Value, 00392 uint8_t u8SPIInstance, 00393 uint8_t u8CSToCG147, 00394 uint8_t u8NOfMessages) 00395 { 00396 /* Declare locals */ 00397 uint16_t au16Message[CG147_INPUT_BUFFER_SIZE]; 00398 uint8_t u8Status; 00399 00400 /* Init variables */ 00401 u8Status = CLEAR; 00402 /* Construct the message only if NOfMessages can be used by au16Message */ 00403 if(N_ELEMENTS(au16Message) >= u8NOfMessages) 00404 { 00405 vfnCG147ComposeFrame(pu8Cmd, pu8Value, (uint16_t*)&au16Message, 00406 u8NOfMessages); 00407 00408 u8Status = u8fnDSPITranscieve(u8SPIInstance, u8CSToCG147, 00409 (uint16_t*)&au16Message, 00410 (uint16_t*)&gau16CG147Responses, 00411 u8NOfMessages); 00412 00413 } 00414 else 00415 { 00416 u8Status = CG147_TRANSCIEVE_ERROR; 00417 } 00418 return (u8Status); 00419 } 00420 00421 /* 00422 ****************************************************************************** 00423 * Function : u8fnCG147ScheduleAOut() 00424 * Functional with Scheduled SPI Tx in 16-bit configuration ONLY 00425 ****************************************************************************** 00426 */ 00427 uint8_t u8fnCG147ScheduleAOut(const uint8_t cu8DSPIInstance, 00428 const uint8_t cu8ChipSelect, 00429 const uint8_t cu8CG147Ch, 00430 uint16_t* pu16Status, 00431 uint32_t* pu32Time) 00432 { 00433 uint8_t u8Status; 00434 00435 u8Status = u8fnCG147ScheduleTransfer(cu8DSPIInstance, cu8ChipSelect, 00436 SBC_AOUT_CTRL, (BIT7 | cu8CG147Ch), 00437 pu16Status, pu32Time); 00438 00439 return (u8Status); 00440 } 00441 /* 00442 ****************************************************************************** 00443 * Function : u8fnCG147ScheduleSPI5Accel() 00444 * Functional with Scheduled SPI Tx in 16-bit configuration ONLY 00445 ****************************************************************************** 00446 */ 00447 uint8_t u8fnCG147SchedulePSI5Accel(const uint8_t cu8DSPIInstance, 00448 const uint8_t cu8ChipSelect, 00449 uint16_t* pu16Accel, 00450 uint32_t* pu32Time) 00451 { 00452 00453 uint8_t u8SPIStatus; 00454 00455 /* Schedule a batch transfer of the defined values in our table */ 00456 u8SPIStatus 00457 = u8fnCG147ScheduleBatchTransfer(cu8DSPIInstance, cu8ChipSelect, 00458 (uint8_t*)cau8ReadPSISensorsCmd, 00459 (uint8_t*)cau8ReadPSISensorsArg, 00460 pu16Accel, 00461 N_ELEMENTS(cau8ReadPSISensorsArg), 00462 pu32Time); 00463 return (u8SPIStatus); 00464 } 00465 /* 00466 ****************************************************************************** 00467 * u8fnCG147ScheduleTransfer 00468 * Functional with Scheduled SPI Tx in 16-bit configuration ONLY 00469 ****************************************************************************** 00470 */ 00471 uint8_t u8fnCG147ScheduleTransfer(uint8_t u8SPIInstance, 00472 uint8_t u8CSToCG147, 00473 uint8_t u8Cmd, 00474 uint8_t u8Value, 00475 uint16_t* pu16Response, 00476 uint32_t* pu32RequestTime) 00477 { 00478 uint8_t u8Status; 00479 uint16_t u16Message; 00480 00481 u8Status = CLEAR; 00482 00483 /* Construct the message only if NOfMessages can be used by au16Message */ 00484 vfnCG147ComposeFrame(&u8Cmd, &u8Value, (uint16_t*)&u16Message, ((uint8_t)1u)); 00485 00486 /* Schedule the transfer */ 00487 u8Status = u8fnSchedDSPIMailTransfer(u8SPIInstance, u8CSToCG147, CLEAR, 00488 CLEAR, (uint16_t*)&u16Message, 00489 pu16Response, ((uint8_t)1u)); 00490 SCHED_WHEN_WAS_THE_LAST_TX_DONE(*pu32RequestTime); 00491 00492 return (u8Status); 00493 } 00494 /* 00495 ****************************************************************************** 00496 * u8fnCG147ScheduleBatchTransfer 00497 * Functional with Scheduled SPI Tx in 16-bit configuration ONLY 00498 ****************************************************************************** 00499 */ 00500 uint8_t u8fnCG147ScheduleBatchTransfer(uint8_t u8SPIInstance, 00501 uint8_t u8CSToCG147, 00502 uint8_t* pu8Cmd, 00503 uint8_t* pu8Value, 00504 uint16_t* pu16Response, 00505 uint8_t u8Size, 00506 uint32_t* pu32RequestTime) 00507 { 00508 uint8_t u8Status; 00509 uint16_t au16Message[CG147_INPUT_BUFFER_SIZE]; 00510 00511 u8Status = CLEAR; 00512 00513 /* Construct the message only if NOfMessages can be used by au16Message */ 00514 vfnCG147ComposeFrame(pu8Cmd, pu8Value, (uint16_t*)&au16Message, u8Size); 00515 00516 /* Schedule the transfer */ 00517 u8Status = u8fnSchedDSPIMailTransfer(u8SPIInstance, u8CSToCG147, CLEAR, 00518 CLEAR, (uint16_t*)&au16Message, 00519 pu16Response, u8Size); 00520 SCHED_WHEN_WAS_THE_LAST_TX_DONE(*pu32RequestTime); 00521 00522 return (u8Status); 00523 } 00524 /* 00525 ****************************************************************************** 00526 * Function : u8fnCG147ScheduleSafeAOut() 00527 * Functional with Scheduled SPI Tx in 17-bit configuration ONLY 00528 ****************************************************************************** 00529 */ 00530 uint8_t u8fnCG147ScheduleSafeAOut(const uint8_t cu8DSPIInstance1, 00531 const uint8_t cu8DSPIInstance2, 00532 const uint8_t cu8ChipSelect, 00533 const uint8_t cu8CG147Ch, 00534 uint32_t* pu32Status, 00535 uint32_t* pu32Time) 00536 { 00537 /* We will schedule a transfer with the AOUT_CTRL message set. */ 00538 return (u8fnCG147ScheduleSafeTransfer(cu8DSPIInstance1, 00539 cu8DSPIInstance2, 00540 cu8ChipSelect, 00541 SBC_AOUT_CTRL, 00542 (BIT7 | cu8CG147Ch), 00543 (uint16_t*)pu32Status, pu32Time)); 00544 00545 } 00546 00547 /* 00548 ****************************************************************************** 00549 * Function : u8fnCG147ScheduleSPI5Accel() 00550 * Functional with Scheduled SPI Tx in 17-bit configuration ONLY 00551 ****************************************************************************** 00552 */ 00553 uint8_t u8fnCG147ScheduleSafePSI5Accel(const uint8_t cu8DSPIInstance1, 00554 const uint8_t cu8DSPIInstance2, 00555 const uint8_t cu8ChipSelect, 00556 const uint16_t cu16ActiveChannels, 00557 uint32_t* pu32RawAccel, 00558 uint32_t* pu32Time) 00559 { 00560 00561 uint8_t u8SPIStatus; 00562 uint8_t u8Counter1; 00563 uint8_t u8Counter2; 00564 uint16_t u16Mask; 00565 uint8_t au8Args[N_ELEMENTS(cau8ReadPSISensorsArg)]; 00566 00567 /* Based on the variable cu16ActiveChannels, we must determine which */ 00568 /* are the active channels in the system. We will reconstruct the */ 00569 /* consant, generic table based out of cau8ReadPSISensorsCmd and Arg */ 00570 /* based on this. */ 00571 /* Init counter to 0 */ 00572 u8Counter1 = CLEAR; 00573 u8Counter2 = CLEAR; 00574 for(u16Mask = CG147_SAT_MASK_MIN; u16Mask < CG147_SAT_MASK_MAX; 00575 u16Mask <<= ((uint16_t)1u)) 00576 { 00577 if(u16Mask & cu16ActiveChannels) 00578 { 00579 au8Args[u8Counter2] = cau8ReadPSISensorsArg[u8Counter1]; 00580 u8Counter2++; 00581 } 00582 else 00583 { 00584 /* Skip this one */ 00585 } 00586 u8Counter1++; 00587 } 00588 00589 /* Finish by writing the last argument to something logical, for example 0 */ 00590 au8Args[u8Counter2++] = CLEAR; 00591 00592 /* Schedule a batch transfer of the defined values in our table */ 00593 u8SPIStatus 00594 = u8fnCG147ScheduleSafeBatchTransfer(cu8DSPIInstance1, cu8DSPIInstance2, 00595 cu8ChipSelect, 00596 (uint8_t*)cau8ReadPSISensorsCmd, 00597 (uint8_t*)au8Args, 00598 (uint16_t*)pu32RawAccel, u8Counter2, 00599 pu32Time); 00600 return (u8SPIStatus); 00601 } 00602 /* 00603 ****************************************************************************** 00604 * Function : u8fnCG147ScheduleSafeSquibFireStart() 00605 * Functional with Scheduled SPI Tx in 17-bit configuration ONLY 00606 ****************************************************************************** 00607 */ 00608 uint8_t u8fnCG147ScheduleSafeSquibFireStart(const uint8_t cu8DSPIInstance1, 00609 const uint8_t cu8DSPIInstance2, 00610 const uint8_t cu8ChipSelect, 00611 uint16_t u16ChannelMask, 00612 uint32_t* pu32Time) 00613 { 00614 uint8_t u8Status; 00615 uint8_t au8LocalArgs[N_ELEMENTS(cau8CG147FireSquibsDfltArgs)]; 00616 00617 /* This function shall be called once the decision to fire has been */ 00618 /* made and all proper checks have taken place. It offers no decision */ 00619 /* making. */ 00620 00621 /* 6. set the external pin EN_FL to high */ 00622 vfnToggleOutputPin(PIN_EN_FL, TRUE); 00623 00624 /* 7. unlock low side and high side power stage by SPI command FLM_LOCK */ 00625 u8Status 00626 = u8fnCG147ScheduleSafeTransfer(cu8DSPIInstance1, cu8DSPIInstance2, 00627 cu8ChipSelect, SBC_FLM_LOCK, 00628 CG147_UNLOCK_HS_LS, 00629 (uint16_t*)gau32CG147DefaultResponses, 00630 pu32Time); 00631 /* 8. turn on low side power stage by SPI command LS_ON */ 00632 00633 /* The mask argument is used to determine which channels will be fired */ 00634 /* using a pre-calculated table to off-load the processor. */ 00635 au8LocalArgs[CLEAR] = cau8SquibOnPrecalc[u16ChannelMask & 0x000Fu]; 00636 au8LocalArgs[1u] = cau8SquibOnPrecalc[(u16ChannelMask >> 4u) & 0x000Fu]; 00637 au8LocalArgs[2u] = cau8SquibOnPrecalc[(u16ChannelMask >> 8u) & 0x000Fu]; 00638 00639 u8Status 00640 |= u8fnCG147ScheduleSafeBatchTransfer( 00641 cu8DSPIInstance1, 00642 cu8DSPIInstance2, 00643 cu8ChipSelect, 00644 (uint8_t*)&cau8CG147FireLSSquibsCmds, 00645 (uint8_t*)&au8LocalArgs, 00646 (uint16_t*)gau32CG147DefaultResponses, 00647 N_ELEMENTS(cau8CG147FireLSSquibsCmds), 00648 pu32Time); 00649 00650 /* 9. wait for 20 us */ 00651 /* We will perform this wait by scheduling a fake SPI transfer. Note */ 00652 /* that Chip Select is clear */ 00653 u8Status 00654 |= u8fnCG147ScheduleSafeBatchTransfer(cu8DSPIInstance1, 00655 cu8DSPIInstance2, 00656 CLEAR, 00657 (uint8_t*)&cau8CG147FireHSSquibsCmds, 00658 (uint8_t*)&cau8CG147FireSquibsDfltArgs, 00659 (uint16_t*)gau32CG147DefaultResponses, 00660 CG147_SPI_FAKE_TIME_20US, pu32Time); 00661 /* 10. turn on highside power stage by SPI command HS_ON */ 00662 u8Status 00663 |= u8fnCG147ScheduleSafeBatchTransfer(cu8DSPIInstance1, 00664 cu8DSPIInstance2, 00665 cu8ChipSelect, 00666 (uint8_t*)&cau8CG147FireHSSquibsCmds, 00667 (uint8_t*)&au8LocalArgs, 00668 (uint16_t*)gau32CG147DefaultResponses, 00669 N_ELEMENTS(cau8CG147FireLSSquibsCmds), 00670 pu32Time); 00671 return (u8Status); 00672 } 00673 /* 00674 ****************************************************************************** 00675 * u8fnCG147ScheduleSafeSquibFireStop 00676 * Functional with Scheduled SPI Tx in 17-bit configuration ONLY 00677 ****************************************************************************** 00678 */ 00679 uint8_t u8fnCG147ScheduleSafeSquibFireStop(const uint8_t cu8DSPIInstance1, 00680 const uint8_t cu8DSPIInstance2, 00681 const uint8_t cu8ChipSelect, 00682 uint32_t* pu32Time) 00683 { 00684 uint8_t u8Status; 00685 00686 /* 1. turn off high side power stage by SPI command HS_ON */ 00687 u8Status 00688 = u8fnCG147ScheduleSafeBatchTransfer(cu8DSPIInstance1, 00689 cu8DSPIInstance2, 00690 cu8ChipSelect, 00691 (uint8_t*)&cau8CG147FireHSSquibsCmds, 00692 (uint8_t*)&cau8CG147FireSquibsDfltArgs, 00693 (uint16_t*)&gau32CG147DefaultResponses, 00694 N_ELEMENTS(cau8CG147FireHSSquibsCmds), 00695 pu32Time); 00696 /* 2. wait for at least 50 us */ 00697 /* We will wait a little longer by making sure the data above has been sent. */ 00698 while(1u > u32fnSchedIsTxDone(*pu32Time)) 00699 { 00700 /* Wait here */ 00701 }; 00702 00703 /* 3. turn off low side power stage by SPI command LS_ON */ 00704 u8Status 00705 |= u8fnCG147ScheduleSafeBatchTransfer(cu8DSPIInstance1, 00706 cu8DSPIInstance2, 00707 cu8ChipSelect, 00708 (uint8_t*)&cau8CG147FireLSSquibsCmds, 00709 (uint8_t*)&cau8CG147FireSquibsDfltArgs, 00710 (uint16_t*)&gau32CG147DefaultResponses, 00711 N_ELEMENTS(cau8CG147FireLSSquibsCmds), 00712 pu32Time); 00713 00714 /* Bring the enable firing loop pin low again */ 00715 vfnToggleOutputPin(PIN_EN_FL, CLEAR); 00716 00717 return (u8Status); 00718 } 00719 /* 00720 ****************************************************************************** 00721 * u8fnCG147ScheduleSafeSquibFireStop 00722 * Functional with Scheduled SPI Tx in 17-bit configuration ONLY 00723 ****************************************************************************** 00724 */ 00725 uint8_t u8fnCG147ScheduleSafeTest(const uint8_t cu8DSPIInstance1, 00726 const uint8_t cu8DSPIInstance2, 00727 const uint8_t cu8ChipSelect, 00728 uint8_t u8TestCase, 00729 uint32_t* pu32Result, 00730 uint16_t* pu16ADCResponses, 00731 uint32_t* pu32Time) 00732 { 00733 uint8_t u8Status; 00734 uint8_t au8ArgsForFirstPart[2u]; 00735 00736 /* No matter what the test is, we need to disable the boost convert */ 00737 /* transistor (T2) first. This is scheduled and hard-coded below. */ 00738 /* Refer to CG147's spec for details. */ 00739 au8ArgsForFirstPart[0u] = ((uint8_t)0x01u); 00740 00741 /* Next we must schedule the actual test. */ 00742 au8ArgsForFirstPart[1u] = u8TestCase; 00743 00744 /* Store the current Voltage level in Aout */ 00745 vfnTransferADCResults(CLEAR, pu16ADCResponses, CG147_N_ADC_DATA); 00746 00747 /* Schedule this transfer */ 00748 u8Status 00749 = u8fnCG147ScheduleSafeBatchTransfer(cu8DSPIInstance1, 00750 cu8DSPIInstance2, 00751 cu8ChipSelect, 00752 (uint8_t*)&cau8CG147TestCmds[CLEAR], 00753 (uint8_t*)&au8ArgsForFirstPart[CLEAR], 00754 (uint16_t*)&gau32CG147DefaultResponses, 00755 CG147_TEST_CMD_SIZE_FIRST_PART, 00756 pu32Time); 00757 00758 /* Depending on the test mode is the amount of time we must wait. */ 00759 if(CG147_TEST_IS_VER_ESR == u8TestCase) 00760 { 00761 /* Specially critical is when VER ESR test is enabled since we cannot */ 00762 /* stay on for more than 100 usec. Since scheduler is set for 100 usec */ 00763 /* SPI transfers, we will wait for the message to be sent plus an */ 00764 /* extra cycle to send the next command. */ 00765 while(1u > u32fnSchedIsTxDone(*pu32Time)) 00766 { 00767 /* Wait here */ 00768 } 00769 /* Now we continue... with less than 100 usec on the clock. */ 00770 } 00771 else 00772 { 00773 /* If this is not the case, we will be waiting no more than 200 msec, */ 00774 /* which is a long time here. We will use a delay fn instead, and allow */ 00775 /* the scheduler to take care of watchdog elements. */ 00776 DELAY_MSEC(CG147_LONG_TEST_WAIT_MS); 00777 /* Store the current Voltage level in Aout */ 00778 /* Enough time has elapsed since the previous request to be able to */ 00779 /* call again without overwriting */ 00780 vfnTransferADCResults(CLEAR, pu16ADCResponses, CG147_N_ADC_DATA); 00781 DELAY_MSEC(2u); 00782 } 00783 00784 /* Now for the grand finale, we must restore original behavior, read back */ 00785 /* results, and move on. */ 00786 u8Status 00787 = u8fnCG147ScheduleSafeBatchTransfer(cu8DSPIInstance1, 00788 cu8DSPIInstance2, 00789 cu8ChipSelect, 00790 (uint8_t*)&cau8CG147TestCmds[CG147_TEST_CMD_SIZE_FIRST_PART], 00791 (uint8_t*)&cau8CG147TestArgs[CG147_TEST_CMD_SIZE_FIRST_PART], 00792 (uint16_t*)pu32Result, 00793 CG147_TEST_CMD_SIZE_SECOND_PART, 00794 pu32Time); 00795 return (u8Status); 00796 } 00797 /* 00798 ****************************************************************************** 00799 * u8fnCG147ScheduleSafeTransfer 00800 * Functional with Scheduled SPI Tx in 17-bit configuration ONLY 00801 ****************************************************************************** 00802 */ 00803 uint8_t u8fnCG147ScheduleSafeTransfer(const uint8_t cu8SPIInstance1, 00804 const uint8_t cu8SPIInstance2, 00805 const uint8_t cu8CSToCG147, 00806 uint8_t u8Cmd, 00807 uint8_t u8Value, 00808 uint16_t* pu16Response, 00809 uint32_t* pu32RequestTime) 00810 { 00811 uint8_t u8Status; 00812 uint16_t u16SafeValue; 00813 uint16_t u16SafeCmd; 00814 uint8_t u8ParityValue; 00815 00816 u8Status = CLEAR; 00817 u16SafeCmd = (uint16_t)u8Cmd; 00818 00819 /* We will construct a safe command by adding a parity bit at the end and */ 00820 /* in so doing, creating a 17-bit word. */ 00821 00822 /* We know that the command part is always Odd */ 00823 /* Calculate the value for the argument only */ 00824 u8ParityValue = u8fnCheckOddParity(u8Value, CLEAR); 00825 00826 /* Store it in a 16-bit variable through an XNOR with a parity bit that */ 00827 /* is always clear. We know this because the command part is always odd. */ 00828 u16SafeValue = (uint16_t)(u8Value << 1u) | (uint16_t)(!u8ParityValue); 00829 00830 /* Schedule the transfer */ 00831 u8Status = u8fnSchedCompositeDSPIMailTransfer(cu8SPIInstance1, 00832 cu8SPIInstance2, cu8CSToCG147, 00833 (uint16_t*)&u16SafeCmd, 00834 (uint16_t*)&u16SafeValue, 00835 (const uint16_t*)pu16Response, 00836 (uint16_t)1u); 00837 SCHED_WHEN_WAS_THE_LAST_TX_DONE(*pu32RequestTime); 00838 00839 return (u8Status); 00840 } 00841 /* 00842 ****************************************************************************** 00843 * u8fnCG147ScheduleSafeBatchTransfer 00844 * Functional with Scheduled SPI Tx in 17-bit configuration ONLY 00845 ****************************************************************************** 00846 */ 00847 uint8_t u8fnCG147ScheduleSafeBatchTransfer(const uint8_t cu8SPIInstance1, 00848 const uint8_t cu8SPIInstance2, 00849 const uint8_t cu8CSToCG147, 00850 uint8_t* pu8Cmd, 00851 uint8_t* pu8Value, 00852 uint16_t* pu16Response, 00853 uint8_t u8Size, 00854 uint32_t* pu32RequestTime) 00855 { 00856 uint8_t u8Status; 00857 uint16_t au16SafeCommand[CG147_INPUT_BUFFER_SIZE]; 00858 uint16_t au16SafeValue[CG147_INPUT_BUFFER_SIZE]; 00859 uint8_t u8ParityValue; 00860 uint8_t u8Counter; 00861 00862 u8Status = CLEAR; 00863 00864 /* We will construct a safe command by adding a parity bit at the end and */ 00865 /* in so doing, creating a 17-bit word. */ 00866 for(u8Counter = CLEAR; u8Counter < u8Size; u8Counter++) 00867 { 00868 /* We know that the command part is always Odd */ 00869 /* Calculate the value for the argument only */ 00870 u8ParityValue = u8fnCheckOddParity(*(pu8Value + u8Counter), CLEAR); 00871 /* Store it in a 16-bit variable through an XNOR with a parity bit that */ 00872 /* is already set. We know this because the command part is always odd. */ 00873 au16SafeValue[u8Counter] = (uint16_t)(*(pu8Value + u8Counter) << 1u) | 00874 (uint16_t)(!u8ParityValue); 00875 au16SafeCommand[u8Counter] = (uint16_t)(*(pu8Cmd + u8Counter)); 00876 } 00877 00878 /* Schedule the transfer */ 00879 u8Status = u8fnSchedCompositeDSPIMailTransfer(cu8SPIInstance1, 00880 cu8SPIInstance2, cu8CSToCG147, 00881 (uint16_t*)au16SafeCommand, 00882 (uint16_t*)&au16SafeValue, 00883 pu16Response, u8Size); 00884 SCHED_WHEN_WAS_THE_LAST_TX_DONE(*pu32RequestTime); 00885 00886 return (u8Status); 00887 } 00888 /* 00889 ****************************************************************************** 00890 * Function : vfnCG147SyncPulse() 00891 ****************************************************************************** 00892 */ 00893 void vfnCG147SyncPulse(const uint8_t cu8NSyncPort, const uint8_t cu8NSyncPin) 00894 { 00895 /* N_SYNC_ON */ 00896 vfnToggleOutputPin(cu8NSyncPort, cu8NSyncPin, TRUE); 00897 (void)u8fnDelay((uint16_t)CG147_PULSE_DELAY_40_USEC); 00898 00899 /* N_SYNC_OFF */ 00900 vfnToggleOutputPin(cu8NSyncPort, cu8NSyncPin, CLEAR); 00901 ; 00902 00903 return; 00904 } 00905 /* 00906 ****************************************************************************** 00907 * Function : WatchDogStartUp() 00908 ****************************************************************************** 00909 */ 00910 uint8_t u8fnCG147WatchDogStartUp(void) 00911 { 00912 00913 /* Init all Watchdog responses */ 00914 gu8CG147WatchDog2ResponseFromMCU = cau8CG147WDResponsesFromMCU[CLEAR]; 00915 gu8CG147WatchDog3ResponseFromMCU = cau8CG147WDResponsesFromMCU[CLEAR]; 00916 gu32CG147WatchDog2RequestToMCU = cau8CG147WDRequestsToMCU[CLEAR]; 00917 gu32CG147WatchDog3RequestToMCU = cau8CG147WDRequestsToMCU[CLEAR]; 00918 00919 return (CLEAR); 00920 } 00921 /* 00922 ****************************************************************************** 00923 * u8fnCG147WatchDogNextWord 00924 ****************************************************************************** 00925 */ 00926 uint8_t u8fnCG147WatchDogNextWord(const uint8_t u8WordFromSBC) 00927 { 00928 uint8_t u8ResponseFromMCU; 00929 uint8_t u8LoopCounter; 00930 00931 /* Init locals */ 00932 u8LoopCounter = CLEAR; 00933 u8ResponseFromMCU = CLEAR; 00934 00935 /* Loop through the defined responses to find ours */ 00936 do 00937 { 00938 if(cau8CG147WDRequestsToMCU[u8LoopCounter] == u8WordFromSBC) 00939 { 00940 if((N_ELEMENTS(cau8CG147WDRequestsToMCU) - 1u) > u8LoopCounter) 00941 { 00942 u8ResponseFromMCU = cau8CG147WDResponsesFromMCU[u8LoopCounter + 1u]; 00943 } 00944 else 00945 { 00946 u8ResponseFromMCU = cau8CG147WDResponsesFromMCU[CLEAR]; 00947 } 00948 } 00949 else 00950 { 00951 /* Nothing */ 00952 } 00953 }while((N_ELEMENTS(cau8CG147WDRequestsToMCU) > u8LoopCounter++) 00954 && (u8ResponseFromMCU == CLEAR)); 00955 00956 /* In case of no error */ 00957 if(u8ResponseFromMCU != CLEAR) 00958 { 00959 /* Nothing */ 00960 } 00961 else 00962 { 00963 /* Error case. Restart the message sequence */ 00964 u8ResponseFromMCU = SBC_WD_RESPONSE_8; 00965 } 00966 00967 return(u8ResponseFromMCU); 00968 } 00969 00970 /* 00971 ****************************************************************************** 00972 * u8fnCG147ComposeFrame 00973 ****************************************************************************** 00974 */ 00975 void vfnCG147ComposeFrame(uint8_t* pu8Cmd, 00976 uint8_t* pu8Value, 00977 uint16_t* pu16ComposedMessage, 00978 uint8_t u8Size) 00979 { 00980 /* All SBC commands use a parity bit that is only calculated with the */ 00981 /* command section of the message. Therefore, the parity can be */ 00982 /* pre-calculated to unload processor tasks. All defines in the */ 00983 /* corresponding .h file have been through this process. This routine */ 00984 /* will no longer calculate it, and the user must make sure that */ 00985 /* the commands are part of the defines, or that parity has been */ 00986 /* calculated prior to calling it. */ 00987 00988 /* Do as long as we have bytes */ 00989 for(; u8Size > CLEAR; u8Size--) 00990 { 00991 /* Construct the message according to the CG147 format: */ 00992 /* BIT15 - BIT9 = Instruction */ 00993 /* BIT8 = Odd parity */ 00994 /* BIT7 - BIT0 = Input data */ 00995 *pu16ComposedMessage = (uint16_t)(*pu8Cmd << BITS_IN_BYTE) | 00996 (uint16_t)*pu8Value; 00997 00998 /* Increment pointers to the next position */ 00999 pu16ComposedMessage++; 01000 pu8Cmd++; 01001 pu8Value++; 01002 } 01003 01004 return; 01005 } 01006 /* 01007 ****************************************************************************** 01008 * u16fnCG147ExtractScheduledPSI5Accel 01009 ****************************************************************************** 01010 */ 01011 uint16_t u16fnCG147ExtractScheduledPSI5Accel(const uint32_t* pu32RawResponse, 01012 uint16_t* pu16Accel, 01013 const uint16_t cu16ChannelsMask) 01014 { 01015 /* Declare locals */ 01016 uint8_t u8Status; 01017 uint16_t u16Status; 01018 uint8_t u8Counter1; 01019 uint8_t u8Counter2; 01020 uint16_t u16LocalMask; 01021 uint8_t u8DummyRead; 01022 01023 /* Init locals */ 01024 u8Status = CLEAR; 01025 u16Status = CLEAR; 01026 u8DummyRead = CLEAR; 01027 u8Counter1 = CLEAR; 01028 u8Counter2 = CLEAR; 01029 01030 /* First element is only to select the first device, but can be ignored */ 01031 /* as long as the status is clear */ 01032 u8Status = u8fnCG147ExtractResponse(pu32RawResponse, (uint8_t*)&u8DummyRead); 01033 01034 /* We will select the next elements based on the passed value u16ChannelsMask */ 01035 for(u16LocalMask = CG147_SAT_MASK_MIN; u16LocalMask < CG147_SAT_MASK_MAX; 01036 u16LocalMask <<= (uint16_t)1u) 01037 { 01038 if(u16LocalMask & cu16ChannelsMask) 01039 { 01040 u8Counter1++; 01041 u8Status = u8fnCG147ExtractPSIAccel((uint32_t*)(pu32RawResponse + u8Counter1), 01042 (uint16_t*)(pu16Accel + u8Counter2)); 01043 if(u8Status != CLEAR) 01044 { 01045 u16Status |= u16LocalMask; 01046 } 01047 else 01048 { 01049 /* Nothing */ 01050 } 01051 } 01052 else 01053 { 01054 01055 } 01056 u8Counter2++; 01057 } 01058 01059 return (u16Status); 01060 } 01061 /* 01062 ****************************************************************************** 01063 * u8fnCG147ExtractPSIAccel 01064 ****************************************************************************** 01065 */ 01066 uint8_t u8fnCG147ExtractPSIAccel(const uint32_t* pu32RawResponse, 01067 uint16_t* pu16Accel) 01068 { 01069 uint8_t u8Status; 01070 01071 u8Status = CLEAR; 01072 01073 /* First verify that the transfered data's parity is correct */ 01074 if(CLEAR == u8fnCG147VerifyParityFromSafeResult(*pu32RawResponse)) 01075 { 01076 /* If we're good, we want to report*/ 01077 u8Status = (uint8_t)(*pu32RawResponse >> BITS_IN_16) 01078 & CG147_ACCEL_STATUS_BYTE_MASK; 01079 *pu16Accel = (uint16_t)((*pu32RawResponse >> 1u) & UCHAR_MAX) 01080 | (uint16_t)((*pu32RawResponse >> BITS_IN_BYTE) 01081 & (CG147_ACCEL_READING_MASK << BITS_IN_BYTE)); 01082 } 01083 else 01084 { 01085 u8Status = CG147_RESPONSE_PARITY_FAILURE; 01086 } 01087 01088 return (u8Status); 01089 } 01090 /* 01091 ****************************************************************************** 01092 * u8fnCG147ExtractResponse 01093 ****************************************************************************** 01094 */ 01095 uint8_t u8fnCG147ExtractResponse(const uint32_t* pu32RawResponse, 01096 uint8_t* pu8Response) 01097 { 01098 uint8_t u8Status; 01099 01100 u8Status = CLEAR; 01101 01102 /* First verify that the transfered data's parity is correct */ 01103 if(CLEAR == u8fnCG147VerifyParityFromSafeResult(*pu32RawResponse)) 01104 { 01105 /* If we're good, we will return the status coming from the device */ 01106 u8Status = (uint8_t)(*pu32RawResponse >> BITS_IN_16) & 01107 CG147_RESPONSE_STATUS_BYTE_MASK; 01108 /* And our response will be that coming from the response minus the */ 01109 /* parity bit, which is at the end */ 01110 *pu8Response = (uint8_t)(*pu32RawResponse >> 1u); 01111 } 01112 else 01113 { 01114 u8Status = CG147_RESPONSE_PARITY_FAILURE; 01115 } 01116 01117 return (u8Status); 01118 } 01119 /* 01120 ****************************************************************************** 01121 * u8fnCG147VerifyParityFromSafeResult 01122 ****************************************************************************** 01123 */ 01124 static uint8_t u8fnCG147VerifyParityFromSafeResult(uint32_t u32ComplexResponse) 01125 { 01126 /* Response is stored as a 32-bit word where the 8MSB of the transfer */ 01127 /* are stored in the second byte, and the 9 LSB are stored in the */ 01128 /* next half. We will need to calculate parity as the combination of */ 01129 /* an 8-bit word + the parity of a 16-bit word. */ 01130 uint8_t u8ParityHigh; 01131 uint8_t u8ParityLow; 01132 01133 u8ParityHigh 01134 = u8fnCheckOddParity((uint8_t)(u32ComplexResponse >> 16u), CLEAR); 01135 u8ParityLow = (uint8_t)u16fnCheckOddParity((uint16_t)u32ComplexResponse, 01136 CLEAR); 01137 01138 return (!(u8ParityHigh ^ u8ParityLow)); 01139 } 01140 /* 01141 ****************************************************************************** 01142 * u16fn10BitOffsetFilter 01143 ****************************************************************************** 01144 */ 01145 uint16_t u16fn10BitOffsetFilter(uint16_t u16RawValue) 01146 { 01147 /* Local variables */ 01148 uint16_t u16CorrectedValue; 01149 01150 /* Init locals to make MISRA happy */ 01151 u16CorrectedValue = CLEAR; 01152 01153 /* Let's check the status of the sign bit and act accordingly */ 01154 if(SIGN_10_BITS == (SIGN_10_BITS & u16RawValue)) 01155 { 01156 u16CorrectedValue = (u16RawValue & MAX_VALUE_10_BITS) - SIGN_10_BITS; 01157 } 01158 else 01159 { 01160 u16CorrectedValue = (u16RawValue & MAX_VALUE_10_BITS) + SIGN_10_BITS; 01161 } 01162 01163 return (u16CorrectedValue); 01164 } 01165 01166 /* 01167 ****************************************************************************** 01168 * vfnCG147WD2Isr 01169 * Functional with Scheduled SPI Tx in 17-bit configuration ONLY 01170 ****************************************************************************** 01171 */ 01172 void vfnCG147WD2Isr(void) 01173 { 01174 01175 /* Calculate the next word */ 01176 /* Increment WD3 counter */ 01177 if(++gu16CG147WatchDog2IsrCount >= CG147_WD2_COUNT_FOR_ISR) 01178 { 01179 gu16CG147WatchDog2IsrCount = CLEAR; 01180 gu8CG147WatchDog2ResponseFromMCU 01181 = u8fnCG147WatchDogNextWord((uint8_t)((gu32CG147WatchDog2RequestToMCU 01182 & 0x1FE) >> 1u)); 01183 01184 if(CLEAR != u8fnCG147ScheduleSafeTransfer(gau8CG147DSPIComplexInstances[0u], 01185 gau8CG147DSPIComplexInstances[1u], 01186 gu8CG147DSPICS, SBC_WD2_TRIGGER, 01187 (uint8_t)gu8CG147WatchDog2ResponseFromMCU, 01188 (uint16_t*)(&gu32CG147WatchDog2RequestToMCU), 01189 (uint32_t*)&gu32CG147WD2Time)) 01190 { 01191 /* Reschedule. */ 01192 gu8RescheduleSource |= RESCH_SRC_2; 01193 vfnPITStart(gu8ReSchPITCh, TRUE); 01194 } 01195 else 01196 { 01197 /* Nothing */ 01198 } 01199 01200 /* Increment WD3 counter */ 01201 if(++gu16CG147WatchDog3IsrCount >= CG147_WD3_COUNT_FOR_ISR) 01202 { 01203 gu16CG147WatchDog3IsrCount = CLEAR; 01204 /* Calculate the next word */ 01205 gu8CG147WatchDog3ResponseFromMCU 01206 = u8fnCG147WatchDogNextWord((uint8_t)((gu32CG147WatchDog3RequestToMCU 01207 & 0x1FE) >> 1u)); 01208 01209 if(CLEAR != u8fnCG147ScheduleSafeTransfer(gau8CG147DSPIComplexInstances[0u], 01210 gau8CG147DSPIComplexInstances[1u], 01211 gu8CG147DSPICS, SBC_WD3_TRIGGER, 01212 (uint8_t)gu8CG147WatchDog3ResponseFromMCU, 01213 (uint16_t*)(&gu32CG147WatchDog3RequestToMCU), 01214 (uint32_t*)&gu32CG147WD3Time)) 01215 { 01216 /* Reschedule. */ 01217 gu8RescheduleSource |= RESCH_SRC_3; 01218 vfnPITStart(gu8ReSchPITCh, TRUE); 01219 } 01220 } 01221 else 01222 { 01223 /* Nothing */ 01224 } 01225 u8fnCG147ScheduleSafeTransfer(gau8CG147DSPIComplexInstances[0u], 01226 gau8CG147DSPIComplexInstances[1u], 01227 gu8CG147DSPICS, SBC_READ_WD_STATUS, 01228 CLEAR, 01229 (uint16_t*)(&gu32CG147WDStatus), 01230 (uint32_t*)&gu32CG147WD2Time); 01231 // u8fnCG147ScheduleSafeTransfer(gau8CG147DSPIComplexInstances[0u], 01232 // gau8CG147DSPIComplexInstances[1u], 01233 // gu8CG147DSPICS, SBC_READ_WD_FC, 01234 // CLEAR, 01235 // (uint16_t*)(&gu32CG147DebugDummy), 01236 // (uint32_t*)&gu32CG147DebugDummy); 01237 } 01238 else 01239 { 01240 /* Nothing */ 01241 } 01242 01243 /* Clear the flag */ 01244 CLEAR_ISR_FLAG(CG147_WD2_ISR_CH); 01245 01246 return; 01247 } 01248 01249 void vfnReScheduleWD(void) 01250 { 01251 /* Clear flag that brought us here */ 01252 CLEAR_ISR_FLAG(SCHED_RESCHED_2); 01253 if(CLEAR == u8fnCG147ScheduleSafeTransfer(gau8CG147DSPIComplexInstances[0u], 01254 gau8CG147DSPIComplexInstances[1u], 01255 gu8CG147DSPICS, SBC_WD2_TRIGGER, 01256 (uint8_t)gu8CG147WatchDog2ResponseFromMCU, 01257 (uint16_t*)(&gu32CG147WatchDog2RequestToMCU), 01258 (uint32_t*)&gu32CG147WD2Time)) 01259 { 01260 gu8RescheduleSource &= ~RESCH_SRC_2; 01261 } 01262 else 01263 { 01264 /* Keep waiting until appropriate */ 01265 } 01266 } 01267 void vfnReScheduleWD3(void) 01268 { 01269 /* Clear flag that brought us here */ 01270 CLEAR_ISR_FLAG(SCHED_RESCHED_3); 01271 if(CLEAR == u8fnCG147ScheduleSafeTransfer(gau8CG147DSPIComplexInstances[0u], 01272 gau8CG147DSPIComplexInstances[1u], 01273 gu8CG147DSPICS, SBC_WD3_TRIGGER, 01274 (uint8_t)gu8CG147WatchDog3ResponseFromMCU, 01275 (uint16_t*)(&gu32CG147WatchDog3RequestToMCU), 01276 (uint32_t*)&gu32CG147WD3Time)) 01277 { 01278 gu8RescheduleSource &= ~RESCH_SRC_3; 01279 } 01280 else 01281 { 01282 /* Keep waiting until appropriate */ 01283 } 01284 } 01285 /* 01286 ****************************************************************************** 01287 * 01288 * End of file. 01289 * 01290 ****************************************************************************** 01291 */